package danny.tools.log;

import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LogAnalyser {
	/**
	 * the string should be like this: 
	 * 170.206.246.75 - - [01/Nov/2007:00:00:00-0700] "GET /wap2/doVote.jsp?s=XVlaEXlTXUoIdgQWFmwRHUdeU1JfCBkaBQQHGB8PHhwSChFWAQ1KARVb HTTP/1.1" 200 3644 "-" "MOT-A-4A/01.01 UP.Browser/4.1.27a1 UP.Link/5.1.2.17"
	 * 
	 * @param str the string which should be parsed
	 *            
	 * @return parsed data
	 * @throws ParseException
	 */
	public static ParsedData parse(String str) throws ParseException {
		ParsedData data = null;
		Pattern pattern = null;
		if (str == null || str.equals(null)) return null;
		// parse ip
		Matcher matcher = Pattern.compile(
				"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}").matcher(str);
		if (matcher.find()) {
			data = new ParsedData();
			data.setIp(str.substring(matcher.start(), matcher.end()));
			str = excludeString(matcher.start(), matcher.end(), str);
		}

		// parse time
		matcher = Pattern.compile("\\[.+\\]").matcher(str);
		if (matcher.find()) {
			data.setTime(str.substring(matcher.start() + 1, matcher.end() - 1));
			str = excludeString(matcher.start(), matcher.end(), str);
		}

		// parse request method
		matcher = Pattern.compile("\"[^\"]+\"").matcher(str);
		if (matcher.find()) {
			data.setRequestMethod(str.substring(matcher.start() + 1, matcher
					.end() - 1));
			str = excludeString(matcher.start(), matcher.end(), str);
		}

		// parse HTTPStatusCode & returnedObjectSize
		matcher = Pattern.compile("[2345]\\d\\d\\s\\d+").matcher(str);
		if (matcher.find()) {
			String[] code = str.substring(matcher.start(), matcher.end())
					.split(" ");
			if (code.length == 2) {
				data.setHTTPStatusCode(code[0]);
				data.setReturnedObjectSize(code[1]);
			} else
				throw new ParseException("Parse error:there are " + code.length
						+ " elements in request.");
			str = excludeString(matcher.start(), matcher.end(), str);
		}

		// parse refer url
		matcher = Pattern.compile("\"[^\"]+\"").matcher(str);
		if (matcher.find()) {
			data.setRefUrl(str
					.substring(matcher.start() + 1, matcher.end() - 1));
			str = excludeString(matcher.start(), matcher.end(), str);
		}

		// parse client string
		matcher = Pattern.compile("\"[^\"]+\"").matcher(str);
		if (matcher.find()) {
			data.setClientStr(str.substring(matcher.start() + 1,
					matcher.end() - 1));
			str = excludeString(matcher.start(), matcher.end(), str);
		}

		return data;
	}

	public static String excludeString(int start, int end, String str) {

		if (start >= end)
			return null;

		String excludeStr = str.substring(0, start) + str.substring(end);

		return excludeStr;
	}

	public static List<ParsedData> readLog(BufferedReader in) {

		List<ParsedData> parsedDatas = new ArrayList<ParsedData>();
		try {
			String line;
			
			do {
				line = in.readLine();
				ParsedData data = parse(line);
				if (data != null) {
					parsedDatas.add(data);
				}
			} while (line != null);
		
		} catch (Exception e) {
			e.printStackTrace();
		}

		return parsedDatas;
	}

	public static void main(String[] args) {

		String strs_valid = "170.206.246.75 - - [01/Nov/2007:00:00:00 -0700] \""
				+ "GET /wap2/doVote.jsp?s=XVlaEXlTXUoIdgQWFmwRHUdeU1JfCBkaBQQHGB8PHhwSChFWAQ1KARVb "
				+ "HTTP/1.1\" 200 3644 \"-\" \"MOT-A-4A/01.01 UP.Browser/4.1.27a1 UP.Link/5.1.2.17\"";
		ParsedData data = LogAnalyser.parse(strs_valid);
		System.out.print(data.getIp());
	}

}
